<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
	<title>script_score 查询 | ElasticSearch 7.7 权威指南中文版</title>
	<meta name="keywords" content="ElasticSearch 权威指南中文版, elasticsearch 7, es7, 实时数据分析，实时数据检索" />
    <meta name="description" content="ElasticSearch 权威指南中文版, elasticsearch 7, es7, 实时数据分析，实时数据检索" />
    <!-- Give IE8 a fighting chance -->
    <!--[if lt IE 9]>
    <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
    <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
	<link rel="stylesheet" type="text/css" href="../static/styles.css" />
	<script>
	var _link = 'query-dsl-script-score-query.html';
    </script>
</head>
<body>
<div class="main-container">
    <section id="content">
        <div class="content-wrapper">
            <section id="guide" lang="zh_cn">
                <div class="container">
                    <div class="row">
                        <div class="col-xs-12 col-sm-8 col-md-8 guide-section">
                            <div style="color:gray; word-break: break-all; font-size:12px;">原英文版地址: <a href="https://www.elastic.co/guide/en/elasticsearch/reference/7.7/query-dsl-script-score-query.html" rel="nofollow" target="_blank">https://www.elastic.co/guide/en/elasticsearch/reference/7.7/query-dsl-script-score-query.html</a>, 原文档版权归 www.elastic.co 所有<br/>本地英文版地址: <a href="../en/query-dsl-script-score-query.html" rel="nofollow" target="_blank">../en/query-dsl-script-score-query.html</a></div>
                        <!-- start body -->
                  <div class="page_header">
<strong>重要</strong>: 此版本不会发布额外的bug修复或文档更新。最新信息请参考 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html" rel="nofollow">当前版本文档</a>。
</div>
<div id="content">
<div class="breadcrumbs">
<span class="breadcrumb-link"><a href="index.html">Elasticsearch 权威指南 [7.7]</a></span>
»
<span class="breadcrumb-link"><a href="query-dsl.html">查询领域特定语言(Query DSL)</a></span>
»
<span class="breadcrumb-link"><a href="specialized-queries.html">专业的查询</a></span>
»
<span class="breadcrumb-node">script_score 查询</span>
</div>
<div class="navheader">
<span class="prev">
<a href="query-dsl-script-query.html">« script 查询</a>
</span>
<span class="next">
<a href="query-dsl-wrapper-query.html">wrapper 查询 »</a>
</span>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h2 class="title">
<a id="query-dsl-script-score-query"></a>script_score 查询
</h2>
</div></div></div>

<p>脚本评分：使用 <a class="xref" href="modules-scripting.html" title="Scripting" rel="nofollow">script(脚本)</a> 为返回的文档提供自定义分数。</p>
<p>
如果评分函数使用成本很高，但只需要计算一组经过过滤的文档的分数，则<code class="literal">script_score</code> 查询非常有用。
</p>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="script-score-query-ex-request"></a>请求示例
</h3>
</div></div></div>
<p>
下面这个 <code class="literal">script_score</code> 查询为每个返回的文档分配一个分数，该分数等于 <code class="literal">likes</code> 字段的值除以 <code class="literal">10</code>。
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "query" : {
        "script_score" : {
            "query" : {
                "match": { "message": "elasticsearch" }
            },
            "script" : {
                "source" : "doc['likes'].value / 10 "
            }
        }
     }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/260.console"></div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="script-score-top-level-params"></a><code class="literal">script_score</code>的顶级参数
</h3>
</div></div></div>
<div class="variablelist">
<dl class="variablelist">
<dt>
<span class="term">
<code class="literal">query</code>
</span>
</dt>
<dd>
(必需, query 对象) 用来返回文档的 query。
</dd>
<dt>
<span class="term">
<code class="literal">script</code>
</span>
</dt>
<dd>
<p>
(必需, <a class="xref" href="modules-scripting-using.html" title="How to use scripts">script 对象</a>) 用于计算<code class="literal">query</code>返回的文档的分数的脚本。
</p>
<div class="important admon">
<div class="icon"></div>
<div class="admon_content">
<p>
<code class="literal">script_score</code> 查询的最终相关性评分不能为负数。

为了支持某些搜索优化，Lucene 要求分数为正数或<code class="literal">0</code>。
</p>
</div>
</div>
</dd>
<dt>
<span class="term">
<code class="literal">min_score</code>
</span>
</dt>
<dd>
(可选, float) 分数低于此浮点数的文档将从搜索结果中排除。
</dd>
<dt>
<span class="term">
<code class="literal">boost</code>
</span>
</dt>
<dd>
(可选, float) 由 <code class="literal">script</code> 产生的文档的分数乘以 <code class="literal">boost</code> 以产生最终的文档的分数。默认为 <code class="literal">1.0</code>。
</dd>
</dl>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="script-score-query-notes"></a>注意
</h3>
</div></div></div>
<div class="section">
<div class="titlepage"><div><div>
<h4 class="title">
<a id="script-score-access-scores"></a>在脚本中使用相关性评分
</h4>
</div></div></div>
<p>在脚本中，你可以访问<a href="modules-scripting-fields.html#scripting-score" class="ulink" target="_top" rel="nofollow">访问</a><code class="literal">_score</code> 变量，该变量表示文档的当前相关性评分。
</p>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h4 class="title">
<a id="script-score-predefined-functions"></a>一些预定义的函数
</h4>
</div></div></div>
<p>
你可以在<code class="literal">script</code>中使用任何可用的<a href="https://www.elastic.co/guide/en/elasticsearch/painless/7.7/painless-contexts.html" class="ulink" target="_top" rel="nofollow">无痛函数(painless function)</a>。

还可以使用下面几个预定义的函数来自定义评分：
</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
<a class="xref" href="query-dsl-script-score-query.html#script-score-saturation" title="Saturation">饱和度 (saturation)</a>
</li>
<li class="listitem">
<a class="xref" href="query-dsl-script-score-query.html#script-score-sigmoid" title="Sigmoid">sigmoid</a>
</li>
<li class="listitem">
<a class="xref" href="query-dsl-script-score-query.html#random-score-function" title="Random score function">随机分数</a>
</li>
<li class="listitem">
<a class="xref" href="query-dsl-script-score-query.html#decay-functions-numeric-fields" title="Decay functions for numeric fields">数值字段的衰减函数</a>
</li>
<li class="listitem">
<a class="xref" href="query-dsl-script-score-query.html#decay-functions-geo-fields" title="Decay functions for geo fields">geo字段的衰减函数</a>
</li>
<li class="listitem">
<a class="xref" href="query-dsl-script-score-query.html#decay-functions-date-fields" title="Decay functions for date fields">date字段的衰减函数</a>
</li>
<li class="listitem">
<a class="xref" href="query-dsl-script-score-query.html#script-score-functions-vector-fields" title="Functions for vector fields">vector字段的函数</a>
</li>
</ul>
</div>
<p>
建议使用这些预定义的函数，而不是编写自己的函数。

这些功能从 Elasticsearch 的内部机制来说更高效。
</p>
<div class="section">
<div class="titlepage"><div><div>
<h5 class="title">
<a id="script-score-saturation"></a>饱和度 (saturation)
</h5>
</div></div></div>
<p><code class="literal">saturation(value,k) = value/(k + value)</code></p>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">"script" : {
    "source" : "saturation(doc['likes'].value, 1)"
}</pre>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h5 class="title">
<a id="script-score-sigmoid"></a>sigmoid
</h5>
</div></div></div>
<p><code class="literal">sigmoid(value, k, a) = value^a/ (k^a + value^a)</code></p>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">"script" : {
    "source" : "sigmoid(doc['likes'].value, 2, 1)"
}</pre>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h5 class="title">
<a id="random-score-function"></a>随机分数函数
</h5>
</div></div></div>
<p><code class="literal">random_score</code> 函数生成从0到1(不包括1)均匀分布的分数。</p>
<p>
<code class="literal">randomScore</code>函数的语法是：<code class="literal">randomScore(&lt;seed&gt;, &lt;fieldName&gt;)</code>。

它有一个作为整数值的必需的参数 <code class="literal">seed</code> 和一个作为字符串值的可选参数 <code class="literal">fieldName</code>。
</p>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">"script" : {
    "source" : "randomScore(100, '_seq_no')"
}</pre>
</div>
<p>
如果省略了参数<code class="literal">fieldName</code>，Lucene 内部的文档 id 将被用作随机性的来源。

这非常有效，但却是不可再现的，因为文档可能会通过合并(merge)重新编号。
</p>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">"script" : {
    "source" : "randomScore(100)"
}</pre>
</div>
<p>
请注意，在同一个分片中具有相同字段值的文档将获得相同的分数，因此通常希望对整个分片中的所有文档使用具有唯一值的字段。

一个好的默认选择可能是使用<code class="literal">_seq_no</code>字段，它唯一的缺点是如果文档被更新，分数将会改变，因为更新操作也会更新<code class="literal">_seq_no</code>字段的值。
</p>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h5 class="title">
<a id="decay-functions-numeric-fields"></a>数值字段的衰减函数
</h5>
</div></div></div>
<p>
你可以在<a href="query-dsl-function-score-query.html#function-decay" class="ulink" target="_top">这里</a>阅读更多关于衰减函数的内容。
</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
<code class="literal">double decayNumericLinear(double origin, double scale, double offset, double decay, double docValue)</code>
</li>
<li class="listitem">
<code class="literal">double decayNumericExp(double origin, double scale, double offset, double decay, double docValue)</code>
</li>
<li class="listitem">
<code class="literal">double decayNumericGauss(double origin, double scale, double offset, double decay, double docValue)</code>
</li>
</ul>
</div>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">"script" : {
    "source" : "decayNumericLinear(params.origin, params.scale, params.offset, params.decay, doc['dval'].value)",
    "params": { <a id="CO58-1"></a><i class="conum" data-value="1"></i>
        "origin": 20,
        "scale": 10,
        "decay" : 0.5,
        "offset" : 0
    }
}</pre>
</div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO58-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>
使用 <code class="literal">params</code> 允许只编译一次脚本，即使 params 改变了。
</p>
</td>
</tr>
</table>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h5 class="title">
<a id="decay-functions-geo-fields"></a>geo字段的衰减函数
</h5>
</div></div></div>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
<code class="literal">double decayGeoLinear(String originStr, String scaleStr, String offsetStr, double decay, GeoPoint docValue)</code>
</li>
<li class="listitem">
<code class="literal">double decayGeoExp(String originStr, String scaleStr, String offsetStr, double decay, GeoPoint docValue)</code>
</li>
<li class="listitem">
<code class="literal">double decayGeoGauss(String originStr, String scaleStr, String offsetStr, double decay, GeoPoint docValue)</code>
</li>
</ul>
</div>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">"script" : {
    "source" : "decayGeoExp(params.origin, params.scale, params.offset, params.decay, doc['location'].value)",
    "params": {
        "origin": "40, -70.12",
        "scale": "200km",
        "offset": "0km",
        "decay" : 0.2
    }
}</pre>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h5 class="title">
<a id="decay-functions-date-fields"></a>date字段的衰减函数
</h5>
</div></div></div>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
<code class="literal">double decayDateLinear(String originStr, String scaleStr, String offsetStr, double decay, JodaCompatibleZonedDateTime docValueDate)</code>
</li>
<li class="listitem">
<code class="literal">double decayDateExp(String originStr, String scaleStr, String offsetStr, double decay, JodaCompatibleZonedDateTime docValueDate)</code>
</li>
<li class="listitem">
<code class="literal">double decayDateGauss(String originStr, String scaleStr, String offsetStr, double decay, JodaCompatibleZonedDateTime docValueDate)</code>
</li>
</ul>
</div>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">"script" : {
    "source" : "decayDateGauss(params.origin, params.scale, params.offset, params.decay, doc['date'].value)",
    "params": {
        "origin": "2008-01-01T01:00:00Z",
        "scale": "1h",
        "offset" : "0",
        "decay" : 0.5
    }
}</pre>
</div>
<div class="note admon">
<div class="icon"></div>
<div class="admon_content">
<p>
date的衰减函数仅限于默认格式和默认时区的日期。
也不支持使用<code class="literal">now</code>进行计算。
</p>
</div>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h5 class="title">
<a id="script-score-functions-vector-fields"></a>vector字段的函数
</h5>
</div></div></div>
<p>
<a class="xref" href="query-dsl-script-score-query.html#vector-functions" title="Functions for vector fields">vector字段的函数</a> 可通过<code class="literal">script_score</code>查询来访问。
</p>
</div>

</div>

<div class="section">
<div class="titlepage"><div><div>
<h4 class="title">
<a id="_allow_expensive_queries_5"></a>允许执行昂贵的查询
</h4>
</div></div></div>
<p>
如果 <a class="xref" href="query-dsl.html#query-dsl-allow-expensive-queries"><code class="literal">search.allow_expensive_queries</code></a> 设置为 <code class="literal">false</code> 则脚本评分查询不会被执行。
</div>

<div class="section">
<div class="titlepage"><div><div>
<h4 class="title">
<a id="script-score-faster-alt"></a>更快的选择
</h4>
</div></div></div>
<p>
<code class="literal">script_score</code> 查询计算每个匹配文档或命中的得分。

有更快的替代查询类型，可以有效地跳过非竞争命中：
</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
如果你想提升一些静态字段的文档，可以使用 <a class="xref" href="query-dsl-rank-feature-query.html" title="Rank feature query"><code class="literal">rank_feature</code></a> 查询。
</li>
<li class="listitem">
如果你想提升与给定日期或地理坐标点更接近的文档，请使用 <a class="xref" href="query-dsl-distance-feature-query.html" title="Distance feature query"><code class="literal">distance_feature</code></a> 查询。
</li>
</ul>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h4 class="title">
<a id="script-score-function-score-transition"></a>从函数评分(function_score)查询转换
</h4>
</div></div></div>
<p>
我们正在废弃 <a class="xref" href="query-dsl-function-score-query.html" title="Function score query"><code class="literal">function_score</code></a> 查询，建议使用 <code class="literal">script_score</code> 查询代替之。
</p>
<p>
可以使用 <code class="literal">script_score</code> 查询从 <code class="literal">function_score</code> 查询实现以下函数：
</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
<a class="xref" href="query-dsl-script-score-query.html#script-score" title="script_score"><code class="literal">script_score</code></a>
</li>
<li class="listitem">
<a class="xref" href="query-dsl-script-score-query.html#weight" title="weight"><code class="literal">weight</code></a>
</li>
<li class="listitem">
<a class="xref" href="query-dsl-script-score-query.html#random-score" title="random_score"><code class="literal">random_score</code></a>
</li>
<li class="listitem">
<a class="xref" href="query-dsl-script-score-query.html#field-value-factor" title="field_value_factor"><code class="literal">field_value_factor</code></a>
</li>
<li class="listitem">
<a class="xref" href="query-dsl-script-score-query.html#decay-functions" title="decay functions"><code class="literal">decay</code> 函数</a>
</li>
</ul>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h5 class="title">
<a id="script-score"></a><code class="literal">script_score</code>
</h5>
</div></div></div>
<p>
你在 函数评分(function_score) 查询中的 <code class="literal">script_score</code> 里的代码，可以直接复制到 脚本评分(script_score) 查询中，无需任何修改。
</p>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h5 class="title">
<a id="weight"></a><code class="literal">weight</code>
</h5>
</div></div></div>
<p>
<code class="literal">weight</code> 函数可以通过下面的脚本在脚本评分查询中实现:
</p>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">"script" : {
    "source" : "params.weight * _score",
    "params": {
        "weight": 2
    }
}</pre>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h5 class="title">
<a id="random-score"></a><code class="literal">random_score</code>
</h5>
</div></div></div>
<p>
像<a class="xref" href="query-dsl-script-score-query.html#random-score-function" title="随机评分函数">随机评分函数(random score function)</a>中描述的那样去使用 <code class="literal">randomScore</code> 函数。
</p>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h5 class="title">
<a id="field-value-factor"></a><code class="literal">field_value_factor</code>
</h5>
</div></div></div>
<p>
<code class="literal">field_value_factor</code> 函数可以通过脚本轻松实现：
</p>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">"script" : {
    "source" : "Math.log10(doc['field'].value * params.factor)",
    "params" : {
        "factor" : 5
    }
}</pre>
</div>
<p>
要检查文档是否有缺失值，可以使用 <code class="literal">doc['field'].size() == 0</code>。

例如，如果文档没有字段 <code class="literal">field</code>，此脚本将使用<code class="literal">1</code>作为它的值：
</p>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">"script" : {
    "source" : "Math.log10((doc['field'].size() == 0 ? 1 : doc['field'].value()) * params.factor)",
    "params" : {
        "factor" : 5
    }
}</pre>
</div>
<p>
下表列出了如何通过脚本实现 <code class="literal">field_value_factor</code> 修饰符：
</p>
<div class="informaltable">
<table border="1" cellpadding="4px">
<colgroup>
<col class="col_1">
<col class="col_2">
</colgroup>
<thead>
<tr>
<th align="left" valign="top">修饰符</th>
<th align="left" valign="top">在脚本评分中的实现</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left" valign="top"><p><code class="literal">none</code></p></td>
<td align="left" valign="top"><p>-</p></td>
</tr>
<tr>
<td align="left" valign="top"><p><code class="literal">log</code></p></td>
<td align="left" valign="top"><p><code class="literal">Math.log10(doc['f'].value)</code></p></td>
</tr>
<tr>
<td align="left" valign="top"><p><code class="literal">log1p</code></p></td>
<td align="left" valign="top"><p><code class="literal">Math.log10(doc['f'].value + 1)</code></p></td>
</tr>
<tr>
<td align="left" valign="top"><p><code class="literal">log2p</code></p></td>
<td align="left" valign="top"><p><code class="literal">Math.log10(doc['f'].value + 2)</code></p></td>
</tr>
<tr>
<td align="left" valign="top"><p><code class="literal">ln</code></p></td>
<td align="left" valign="top"><p><code class="literal">Math.log(doc['f'].value)</code></p></td>
</tr>
<tr>
<td align="left" valign="top"><p><code class="literal">ln1p</code></p></td>
<td align="left" valign="top"><p><code class="literal">Math.log(doc['f'].value + 1)</code></p></td>
</tr>
<tr>
<td align="left" valign="top"><p><code class="literal">ln2p</code></p></td>
<td align="left" valign="top"><p><code class="literal">Math.log(doc['f'].value + 2)</code></p></td>
</tr>
<tr>
<td align="left" valign="top"><p><code class="literal">square</code></p></td>
<td align="left" valign="top"><p><code class="literal">Math.pow(doc['f'].value, 2)</code></p></td>
</tr>
<tr>
<td align="left" valign="top"><p><code class="literal">sqrt</code></p></td>
<td align="left" valign="top"><p><code class="literal">Math.sqrt(doc['f'].value)</code></p></td>
</tr>
<tr>
<td align="left" valign="top"><p><code class="literal">reciprocal</code></p></td>
<td align="left" valign="top"><p><code class="literal">1.0 / doc['f'].value</code></p></td>
</tr>
</tbody>
</table>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h5 class="title">
<a id="decay-functions"></a>衰减(<code class="literal">decay</code>)函数
</h5>
</div></div></div>
<p>
<code class="literal">script_score</code> 查询具有可在脚本中使用的等效的<a class="xref" href="query-dsl-script-score-query.html#decay-functions" title="decay functions">衰减函数(decay function)</a>。
</p>
</div>

</div>

<div class="section xpack">
<div class="titlepage"><div><div>
<h4 class="title">
<a id="vector-functions"></a>vector字段的函数
</h4>
</div></div></div>
<div class="note admon">
<div class="icon"></div>
<div class="admon_content">
<p>
在向量(vector)函数的计算过程中，所有匹配的文档都被线性扫描。

因此，预计查询时间会随着匹配文档的数量而线性增长。

因此，建议使用 <code class="literal">query</code> 参数来限制匹配文档的数量。
</p>
</div>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h5 class="title">
<a id="_dense_vector_functions"></a><code class="literal">dense_vector</code>函数
</h5>
</div></div></div>
<p>
让我们创建一个带有<code class="literal">dense_vector</code>类型的映射的索引，然后添加并索引几个文档进去。
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">PUT my_index
{
  "mappings": {
    "properties": {
      "my_dense_vector": {
        "type": "dense_vector",
        "dims": 3
      },
      "status" : {
        "type" : "keyword"
      }
    }
  }
}

PUT my_index/_doc/1
{
  "my_dense_vector": [0.5, 10, 6],
  "status" : "published"
}

PUT my_index/_doc/2
{
  "my_dense_vector": [-0.5, 10, 10],
  "status" : "published"
}

POST my_index/_refresh</pre>
</div>
<div class="console_widget" data-snippet="snippets/261.console"></div>
<p>
<code class="literal">cosineSimilarity</code> 函数计算给定的查询向量(query_vector) 和文档向量(vector) 之间的余弦相似度。
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET my_index/_search
{
  "query": {
    "script_score": {
      "query" : {
        "bool" : {
          "filter" : {
            "term" : {
              "status" : "published" <a id="CO59-1"></a><i class="conum" data-value="1"></i>
            }
          }
        }
      },
      "script": {
        "source": "cosineSimilarity(params.query_vector, 'my_dense_vector') + 1.0", <a id="CO59-2"></a><i class="conum" data-value="2"></i>
        "params": {
          "query_vector": [4, 3.4, -0.2]  <a id="CO59-3"></a><i class="conum" data-value="3"></i>
        }
      }
    }
  }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/262.console"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO59-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>
要限制应用到脚本评分计算的文档数量，请提供一个 filter。
</p>
</td>
</tr>
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO59-2"><i class="conum" data-value="2"></i></a></p>
</td>
<td align="left" valign="top">
<p>
该脚本将余弦相似度加 1.0，以防止分数为负。
</p>
</td>
</tr>
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO59-3"><i class="conum" data-value="3"></i></a></p>
</td>
<td align="left" valign="top">
<p>
为了利用脚本优化，提供一个 查询向量(query_vector) 作为脚本参数。
</p>
</td>
</tr>
</table>
</div>
<div class="note admon">
<div class="icon"></div>
<div class="admon_content">
<p>
如果文档的 dense_vector 字段的维数与 查询向量(query_vector) 的维数不同，将会抛出一个错误。
</p>
</div>
</div>
<p>
<code class="literal">dotProduct</code> 函数计算给定的查询向量(query_vector) 和文档的向量(vector) 之间的点积。
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET my_index/_search
{
  "query": {
    "script_score": {
      "query" : {
        "bool" : {
          "filter" : {
            "term" : {
              "status" : "published"
            }
          }
        }
      },
      "script": {
        "source": """
          double value = dotProduct(params.query_vector, 'my_dense_vector');
          return sigmoid(1, Math.E, -value); <a id="CO60-1"></a><i class="conum" data-value="1"></i>
        """,
        "params": {
          "query_vector": [4, 3.4, -0.2]
        }
      }
    }
  }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/263.console"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO60-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>使用标准的 sigmoid 函数可以防止分数为负。</p>
</td>
</tr>
</table>
</div>
<p>
<code class="literal">l1norm</code> 函数计算给定的查询向量(query_vector) 和文档向量(vector) 之间的 L<sup>1</sup>距离(曼哈顿距离)。
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET my_index/_search
{
  "query": {
    "script_score": {
      "query" : {
        "bool" : {
          "filter" : {
            "term" : {
              "status" : "published"
            }
          }
        }
      },
      "script": {
        "source": "1 / (1 + l1norm(params.queryVector, 'my_dense_vector'))", <a id="CO61-1"></a><i class="conum" data-value="1"></i>
        "params": {
          "queryVector": [4, 3.4, -0.2]
        }
      }
    }
  }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/264.console"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO61-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>
与表示相似性的 <code class="literal">cosineSimilarity</code> 不同，下面显示的 <code class="literal">l1norm</code> 和 <code class="literal">l2norm</code> 表示距离或差异。

这意味着，向量(vector)越相似，<code class="literal">l1norm</code> 和 <code class="literal">l2norm</code> 函数产生的分数越低。

因此，因为我们需要更多相似的向量(vector)来获得更高的分数，所以我们颠倒了 <code class="literal">l1norm</code> 和 <code class="literal">l2norm</code> 的输出。

此外，为了避免文档向量(vector)与查询完全匹配时被 0 除，我们在分母中添加了 <code class="literal">1</code>。
</p>
</td>
</tr>
</table>
</div>
<p>
<code class="literal">l2norm</code> 函数计算给定的查询向量(query_vector) 和文档向量(vector) 之间的 L<sup>2</sup>距离(欧几里德距离)。
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET my_index/_search
{
  "query": {
    "script_score": {
      "query" : {
        "bool" : {
          "filter" : {
            "term" : {
              "status" : "published"
            }
          }
        }
      },
      "script": {
        "source": "1 / (1 + l2norm(params.queryVector, 'my_dense_vector'))",
        "params": {
          "queryVector": [4, 3.4, -0.2]
        }
      }
    }
  }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/265.console"></div>
<div class="note admon">
<div class="icon"></div>
<div class="admon_content">
<p>
如果文档没有执行 向量(vector) 函数的 vector 字段的值，将会抛出一个错误。
</p>
</div>
</div>
<p>
可以通过 <code class="literal">doc['my_vector'].size() == 0</code> 检查文档的字段<code class="literal">my_vector</code>是否有值。

整个脚本可能如下所示:
</p>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">"source": "doc['my_vector'].size() == 0 ? 0 : cosineSimilarity(params.queryVector, 'my_vector')"</pre>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h5 class="title">
<a id="_sparse_vector_functions"></a><code class="literal">sparse_vector</code>函数
</h5>
</div></div></div>
<div class="warning admon">
<div class="icon"></div>
<div class="admon_content">
<h3>在 7.6 中废弃。</h3>
<p><code class="literal">sparse_vector</code>类型已废弃并将在8.0版本中移除。</p>
</div>
</div>
<p>我们来创建一个包含<code class="literal">sparse_vector</code>类型的映射的索引，添加并索引几个文档进去：</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">PUT my_sparse_index
{
  "mappings": {
    "properties": {
      "my_sparse_vector": {
        "type": "sparse_vector"
      },
      "status" : {
        "type" : "keyword"
      }
    }
  }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/266.console"></div>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">PUT my_sparse_index/_doc/1
{
  "my_sparse_vector": {"2": 1.5, "15" : 2, "50": -1.1, "4545": 1.1},
  "status" : "published"
}

PUT my_sparse_index/_doc/2
{
  "my_sparse_vector": {"2": 2.5, "10" : 1.3, "55": -2.3, "113": 1.6},
  "status" : "published"
}

POST my_sparse_index/_refresh</pre>
</div>
<div class="console_widget" data-snippet="snippets/267.console"></div>
<p>
<code class="literal">cosineSimilaritySparse</code> 函数计算给定的查询向量(query_vector) 和文档向量(vector) 之间的余弦相似性。
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET my_sparse_index/_search
{
  "query": {
    "script_score": {
      "query" : {
        "bool" : {
          "filter" : {
            "term" : {
              "status" : "published"
            }
          }
        }
      },
      "script": {
        "source": "cosineSimilaritySparse(params.query_vector, 'my_sparse_vector') + 1.0",
        "params": {
          "query_vector": {"2": 0.5, "10" : 111.3, "50": -1.3, "113": 14.8, "4545": 156.0}
        }
      }
    }
  }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/268.console"></div>
<p>
<code class="literal">dotProductSparse</code> 函数计算给定的查询向量(query_vector) 和文档向量(vector) 之间的点积。
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET my_sparse_index/_search
{
  "query": {
    "script_score": {
      "query" : {
        "bool" : {
          "filter" : {
            "term" : {
              "status" : "published"
            }
          }
        }
      },
      "script": {
        "source": """
          double value = dotProductSparse(params.query_vector, 'my_sparse_vector');
          return sigmoid(1, Math.E, -value);
        """,
         "params": {
          "query_vector": {"2": 0.5, "10" : 111.3, "50": -1.3, "113": 14.8, "4545": 156.0}
        }
      }
    }
  }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/269.console"></div>
<p>
<code class="literal">l1normSparse</code> 函数计算给定的查询向量(query_vector) 和文档向量(vector) 之间的 L<sup>1</sup> 距离。
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET my_sparse_index/_search
{
  "query": {
    "script_score": {
      "query" : {
        "bool" : {
          "filter" : {
            "term" : {
              "status" : "published"
            }
          }
        }
      },
      "script": {
        "source": "1 / (1 + l1normSparse(params.queryVector, 'my_sparse_vector'))",
        "params": {
          "queryVector": {"2": 0.5, "10" : 111.3, "50": -1.3, "113": 14.8, "4545": 156.0}
        }
      }
    }
  }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/270.console"></div>
<p>
<code class="literal">l2normSparse</code> 函数计算给定的查询向量(query_vector) 和文档向量(vector) 之间的 L<sup>2</sup> 距离。
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET my_sparse_index/_search
{
  "query": {
    "script_score": {
      "query" : {
        "bool" : {
          "filter" : {
            "term" : {
              "status" : "published"
            }
          }
        }
      },
      "script": {
        "source": "1 / (1 + l2normSparse(params.queryVector, 'my_sparse_vector'))",
        "params": {
          "queryVector": {"2": 0.5, "10" : 111.3, "50": -1.3, "113": 14.8, "4545": 156.0}
        }
      }
    }
  }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/271.console"></div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h5 class="title">
<a id="score-explanation"></a>explain(解释)请求
</h5>
</div></div></div>
<p>
使用<a class="xref" href="search-explain.html" title="Explain API" rel="nofollow">explain请求</a>可以查看如何计算分数的解释。

<code class="literal">script_score</code> 查询可以通过设置参数 <code class="literal">explanation</code> 来添加自己的解释：
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /twitter/_explain/0
{
    "query" : {
        "script_score" : {
            "query" : {
                "match": { "message": "elasticsearch" }
            },
            "script" : {
                "source" : """
                  long likes = doc['likes'].value;
                  double normalizedLikes = likes / 10;
                  if (explanation != null) {
                    explanation.set('normalized likes = likes / 10 = ' + likes + ' / 10 = ' + normalizedLikes);
                  }
                  return normalizedLikes;
                """
            }
        }
     }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/272.console"></div>
<p>
注意，当在普通的 <code class="literal">_search</code> 请求中使用时，explanation 将为 null，因此使用条件保护是最佳实践。
</p>
</div>

</div>

</div>

</div>
<div class="navfooter">
<span class="prev">
<a href="query-dsl-script-query.html">« script 查询</a>
</span>
<span class="next">
<a href="query-dsl-wrapper-query.html">wrapper 查询 »</a>
</span>
</div>
</div>

                  <!-- end body -->
                        </div>
                        <div class="col-xs-12 col-sm-4 col-md-4" id="right_col">
                        
                        </div>
                    </div>
                </div>
            </section>
        </div>
    </section>
</div>
<script src="../static/cn.js"></script>
</body>
</html>